
#include <bancoodbc.h>

/**
 * \param arq_conf passagem do caminho do arquivo de configuração da conexao com o banco de dados.
 */
BANCOODBC::BANCOODBC(string al, string us, string se)
  	{
	alias.clear();
	alias = al;
	username.clear();
	username = us;
	senha.clear();
	senha = se;
	//this->conn = NULL;
	this->query_result = 0;
	
  	this->conectar();
  	}

BANCOODBC::~BANCOODBC()
	{
	if (conectado)
		{
		SQLDisconnect(conn);
		}
	SQLFreeHandle(SQL_HANDLE_DBC, conn);
  	SQLFreeHandle(SQL_HANDLE_ENV, env);
	}

void BANCOODBC::conectar()
	{
	char *aux;
	mensagem.clear();
	conectado = false;
	// 1. allocate Environment handle and register version 
	ret = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&env);
	if (SQL_SUCCEEDED(ret))
		{
		ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
		if (SQL_SUCCEEDED(ret))
			{
			ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
			if (SQL_SUCCEEDED(ret))
				{
				SQLSetConnectAttr(conn, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0);
				ret = SQLConnect(conn, (SQLCHAR*)alias.c_str(), SQL_NTS, (SQLCHAR*)username.c_str(), SQL_NTS, (SQLCHAR*)senha.c_str(),  SQL_NTS);
			  	if (SQL_SUCCEEDED(ret))
					{
					this->conectado = true;
					query_result = 1;
					this->mensagem = "Conectado com sucesso!\n";
					}
			  	else
					{
					this->conectado = false;
					query_result = 3;
					aux = new char[32];
					sprintf(aux, "Error SQLConnect: %d\n",ret);
					mensagem.append(aux);
					delete aux;
					SQLGetDiagRec(SQL_HANDLE_DBC, conn,1, stat, &erro,msg,100,&mlen);
					aux = new char[sizeof(msg)+1];
					sprintf(aux,"%s",msg);
					mensagem.append(aux);
					delete aux;
					aux = new char[32];
					sprintf(aux, "(%d)\n",erro);
					mensagem.append(aux);
					delete aux;
					}
				}
			else
				{
				query_result = 3;
				mensagem = "Erro AllocHandle CONN";
				}
			}
		else
			{
			query_result = 3;
			mensagem = "Erro SQLSetEnvAttr ";
			}
		}
	else
		{
		query_result = 3;
		mensagem = "Erro AllocHandle ENV";
		}
 	}

/**
 * \param query recebe uma consulta SQL que será executada na base de dados.
 */
void BANCOODBC::executar(char *query)
	{
	int j,i;
	char *aux;
	SQLHSTMT st_query;
	SQLSMALLINT colunaz;
	SQLLEN linhaz;
	SQLCHAR NomeColuna[MAX_DATA_WIDTH+1];
	char *dados;
	ofstream log;

	log.open("testando.log");
	mensagem.clear();
	if (conectado)
		{
		//log << __FILE__ << ": " << __LINE__ << endl;
		ret = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
		if (SQL_SUCCEEDED(ret))
			{
			//log << __FILE__ << ": " << __LINE__ << endl;
			ret = SQLExecDirect( stmt, (SQLCHAR*)query, SQL_NTS);
			if (SQL_SUCCEEDED(ret))
				{
				ret = SQLNumResultCols(stmt,&colunaz);
				//log << __FILE__ << ": " << __LINE__ << endl;
				//log << ret << "  " << colunaz << endl;
				if (SQL_SUCCEEDED(ret))
					{
					colunas = colunaz;
					if (colunas > 0)
						{
						nome_colunas.clear();
						for (i=1; i <= colunas; i++)
							{
							SQLColAttribute( stmt, i, SQL_DESC_LABEL, NomeColuna, sizeof(NomeColuna), NULL, NULL );
							dados = new char[sizeof(NomeColuna)+1];
							sprintf(dados,"%s",NomeColuna);
							nome_colunas.push_back (dados);
							delete dados;
							}
						}
					ret = SQLRowCount(stmt,&linhaz);
					//log << ret << "  " << linhaz << endl;
					//log << __FILE__ << ": " << __LINE__ << endl;
					if (SQL_SUCCEEDED(ret))
						{
						resultado();
						log << registros << endl;
						if (registros > 0)
							{
							query_result = 2;
							mensagem = "Executada com Sucesso!\n" ;
							}
						else
							{
							query_result = 1;
							mensagem = "Executada com Sucesso!\n" ;
							}
						}
					}
				else
					{
					query_result = 1;
					mensagem = "Executada com Sucesso!\n" ;
					}
				}
			else
				{
				query_result = 3;
				mensagem = "Erro ao preparar SQL\n";
				mensagem.append(query);
				SQLGetDiagRec(SQL_HANDLE_DBC, conn,1, stat,&erro,msg,100,&mlen);
				aux = new char[sizeof(msg)+1];
				sprintf(aux,"\n%s",msg);
				mensagem.append(aux);
				delete aux;
				aux = new char[32];
				sprintf(aux,"(%d)\n",erro);
				mensagem.append(aux);
				delete aux;
				}
			}
		else
			{	
			mensagem = "Fehler im AllocStatement \n";
			SQLGetDiagRec(SQL_HANDLE_DBC, conn,1, stat,&erro,msg,100,&mlen);
			aux = new char[sizeof(msg)+1];
			sprintf(aux,"%s",msg);
			mensagem.append(aux);
			delete aux;
			aux = new char[32];
			sprintf(aux,"(%d)\n",erro);
			mensagem.append(aux);
			delete aux;
			}
		}
	//log.close();
	}

void BANCOODBC::resultado()
	{
	int i, j;
	vector<string> valores;
	SQLCHAR Dados[MAX_DATA_WIDTH+1];
	char *dados;
	SQLRETURN ret_data, retorno;
	SQLLEN indicacao = 0;

	resultados.clear();
	retorno = SQLFetch( stmt );
	registros = 0;
	while (retorno != SQL_NO_DATA)
		{
		valores.clear();
		for (j=1; j <= colunas; j++)
			{
			ret_data = SQLGetData( stmt, j, SQL_C_CHAR, (SQLPOINTER)Dados, sizeof(Dados), &indicacao);
			Dados[MAX_DATA_WIDTH] = '\0';
			if (SQL_SUCCEEDED(ret_data) && indicacao != SQL_NULL_DATA )
				{
				dados = new char[sizeof(Dados)+1];
				sprintf(dados,"%s",Dados);
				valores.push_back (dados);
				delete dados;
				}
			else if (ret_data == SQL_ERROR)
				{
				valores.push_back ((char *)"ERRO");
				}
			else
				{
				valores.push_back ("null");
				}
			}
		resultados.push_back (valores);
		retorno = SQLFetch( stmt );
		registros++;
		}
	}
